
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>Redis缓存相关问题 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>Redis缓存相关问题 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">什么是缓存穿透？它发生的核心原因是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">缓存穿透是指当请求一个数据库中根本不存在的数据时，由于缓存中也无法命中，导致请求每次都直接访问数据源（数据库），从而可能压垮数据源。核心原因是请求的key对应的数据在数据库中不存在。</div>
          </div>
          <div class="card-source">来源: 1.缓存穿透 -> 1.1出现的原理</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">布隆过滤器（Bloom Filter）是如何帮助解决缓存穿透问题的？它的核心作用是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">布隆过滤器可以用来快速判断一个元素是否存在于集合中。在解决缓存穿透时，它的核心作用是判断某个key“一定不存在或者可能存在”。如果判断为一定不存在，就可以直接拦截请求，避免查询缓存和数据库，从而保护数据源。</div>
          </div>
          <div class="card-source">来源: 1.缓存穿透 -> 1.2.3布隆过滤器</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">缓存击穿和缓存雪崩的主要区别是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">主要区别在于查询的数据范围和原因。缓存击穿是指大量并发请求集中查询“同一条”数据，而这条数据刚好缓存过期。缓存雪崩则是指“大量不同”的数据在同一时间点集体过期，导致大量对不同数据的查询都直接落到数据库上。</div>
          </div>
          <div class="card-source">来源: 2 缓存雪崩 -> 3.1出现的原理</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">针对缓存击穿问题，文档中提到了哪两种解决方法？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">文档中提到的解决方法有两种：1. 将热点数据（如爆款商品）设置为永不过期。 2. 使用锁机制，确保在缓存失效时只有一个线程去数据库加载数据，其他线程等待。</div>
          </div>
          <div class="card-source">来源: 1 缓存击穿 -> 2.1解决方式</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">如何有效防止缓存雪崩的发生？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">文档中提到了两种方法：1. 将缓存数据的过期时间设置成一个随机值，防止大量数据在同一时间集中过期。 2. 将热点数据设置为永不过期。</div>
          </div>
          <div class="card-source">来源: 2 缓存雪崩 -> 3.2解决方式</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">什么是缓存预热？它的主要目的是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">缓存预热是在系统上线后，主动将相关的缓存数据直接加载到缓存系统中。其主要目的是避免用户在首次请求时因缓存未命中而去查询数据库，让用户的请求能够直接从事先加载好的缓存中获取数据。</div>
          </div>
          <div class="card-source">来源: 4.缓存预热</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">除了缓存服务器自带的策略，文档中还提到了哪两种自定义的缓存更新策略？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">文档中提到了两种自定义策略：1. 定时去清理过期的缓存。 2. 当有用户请求时，再判断该请求所用到的缓存是否过期，如果过期则去底层系统获取新数据并更新缓存。</div>
          </div>
          <div class="card-source">来源: 5.缓存更新</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">特性</div>
          <div class="card-question">在Redis的缓存淘汰策略中，`Volatile-ttl` 策略是如何工作的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">特性</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`Volatile-ttl` 策略仅限于对设置了过期时间（expire）的键值对起作用。当内存不足时，它会优先删除剩余生存时间（TTL）最短的key。</div>
          </div>
          <div class="card-source">来源: 3 缓存数据的淘汰策略</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">请解释缓存淘汰算法中 LRU 和 LFU 的核心区别。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">核心区别在于判断淘汰的依据不同。LRU (Least Recently Used) 算法是根据“使用时间的远近”来决定的，它会淘汰近期最少被使用的数据。而 LFU (Least Frequently Used) 算法是根据“使用次数的多少”来决定的，它会淘汰在一段时间内被使用次数最少的数据。</div>
          </div>
          <div class="card-source">来源: 4 缓存淘汰算法</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
